package logic

import (
	"fmt"
	"game/src/common"
	"game/src/common/impl"
	"game/src/conf"
	"net"
)

var _ common.IServer = &Server{}

type Server struct {
	ServerId   int
	ServerName string
	IP         string
	IPVersion  string
	Port       int
	//当前Server的消息管理模块，用来绑定MsgId和对应的处理方法
	msgHandler common.IMsgHandle
	//当前Server的链接管理器
	ConnMgr   common.IConnManager
	OnlineMgr *OnlineManager

	// =======================
	//新增两个hook函数原型

	//该Server的连接创建时 Hook 函数
	OnConnStart func(conn common.IConnection)
	//该Server的连接断开时的Hook函数
	OnConnStop func(conn common.IConnection)

	// =======================
}

var GameServer *Server

func NewServer() {
	conf.InitConfig()

	GameServer = &Server{
		ServerName: conf.GameConfig.Name,
		IPVersion:  "tcp4",
		IP:         conf.GameConfig.Host,
		Port:       conf.GameConfig.TcpPort,
		msgHandler: impl.NewMsgHandle(),
		ConnMgr:    NewConnManager(),   //创建ConnManager
		OnlineMgr:  NewOnlineManager(), //创建ConnManager
	}
}

// GetConnMgr 得到链接管理
func (s *Server) GetConnMgr() common.IConnManager {
	return s.ConnMgr
}

func (s *Server) GetOnlineMgr() *OnlineManager {
	return s.OnlineMgr
}

func (s *Server) AddRouter(msgId uint32, router common.IRouter) {
	s.msgHandler.AddRouter(msgId, router)
}

// SetOnConnStart 设置该Server的连接创建时Hook函数
func (s *Server) SetOnConnStart(hookFunc func(common.IConnection)) {
	s.OnConnStart = hookFunc
}

// SetOnConnStop 设置该Server的连接断开时的Hook函数
func (s *Server) SetOnConnStop(hookFunc func(common.IConnection)) {
	s.OnConnStop = hookFunc
}

// DoConnectionBegin 创建连接的时候执行
func DoConnectionBegin(conn common.IConnection) {
	GameServer.GetConnMgr().Add(conn)
}

// DoConnectionLost 连接断开的时候执行
func DoConnectionLost(conn common.IConnection) {

	if i, err := conn.GetProperty("role"); err != nil {
		fmt.Println("ERR: Conn Property Role 丢失")
	} else {
		role := *i.(**Role)
		GameServer.GetOnlineMgr().Remove(role)
	}
	GameServer.GetConnMgr().Remove(conn)
	fmt.Println("DoConneciotnLost is Called ... ")
}

// CallOnConnStart 调用连接OnConnStart Hook函数
func (s *Server) CallOnConnStart(conn common.IConnection) {
	if s.OnConnStart != nil {
		fmt.Println("---> CallOnConnStart....")
		s.OnConnStart(conn)
	}
}

// CallOnConnStop 调用连接OnConnStop Hook函数
func (s *Server) CallOnConnStop(conn common.IConnection) {
	if s.OnConnStop != nil {
		fmt.Println("---> CallOnConnStop....")
		s.OnConnStop(conn)
	}
}
func (s *Server) Start() {
	fmt.Printf("[START] Server listrnner at IP: %s, Port: %d, is starting.\n", s.IP, s.Port)
	//注册链接hook回调函数
	s.SetOnConnStart(DoConnectionBegin)
	s.SetOnConnStop(DoConnectionLost)
	go func() {
		//0 启动worker工作池机制
		s.msgHandler.StartWorkerPool()

		// 1. 生成 tcp address
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
		if err != nil {
			fmt.Println("resolve tcp addr err:", err)
			return
		}
		// 2. 监听 address
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Printf("listen %s err %s", s.IPVersion, err)
			return
		}
		fmt.Printf("start server %s succ, now listenning...\n", s.ServerName)
		// todo server.go need a func that automatically produces ID
		var cid uint32 = 0
		// 3 start server net businesses
		for {
			conn, err := listener.AcceptTCP()
			// AcceptTCP 进入阻塞状态，并等待新的TCP连接
			if err != nil {
				fmt.Println("Accept err ", err)
				continue
			}
			fmt.Println("Accept succ")
			// 3.2 todo Server.Start() set max connections
			//=============
			////3.2 设置服务器最大连接控制,如果超过最大连接，那么则关闭此新的连接
			//if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
			//	_ = conn.Close()
			//	continue
			//}
			//=============
			//3.3 处理该新连接请求的 业务 方法， 此时应该有 handler 和 conn是绑定的
			dealConn := impl.NewConnection(s, conn, cid, s.msgHandler)
			cid++
			//3.4 启动当前链接的处理业务
			go dealConn.Start()
		}
	}()
}

func (s *Server) Stop() {
	fmt.Println("[STOP server, name ", s.ServerName)
	//将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
	s.ConnMgr.ClearConn()
}

//func (s *Server) Server() {
//	s.Start()
//
//	// todo perfect Server.server() execution conditions
//	for {
//		time.Sleep(10 * time.Second)
//	}
//}
